home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / go32 / extdebug.c < prev    next >
C/C++ Source or Header  |  1993-08-15  |  8KB  |  292 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h>
  4. #include <io.h>
  5. #include <string.h>
  6. #include <dos.h>
  7.  
  8. #include "gotypes.h"
  9. #include "aout.h"
  10. #include "extdebug.h"
  11. #include "dpmi.h"
  12. #include "paging.h"
  13. #include "tss.h"
  14. #include "exphdlr.h"
  15. #include "mswitch.h"
  16. #include "utils.h"
  17. #include "gdt.h"
  18. #include "utils.h"
  19. #include "eventque.h"
  20.  
  21. extern EventQueue *event_queue;
  22. extern word32 dr[8];
  23. extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
  24. extern DPMImemory DPMImem;              /* DPMI arena address from paging.c */
  25.  
  26. static ExternalDebuggerInfo ext_debug_info;
  27. int using_external_debugger = 0;
  28. static word16 ourDSsel;
  29. static int breakhandle[4],nset;   /* for DPMI breakpoints */
  30.  
  31. #define VCPI_ED 1
  32.  
  33. void load_external_debugger(char *fn, char *running_fname, char *argv0)
  34. {
  35.   FILEHDR eh;
  36.   GNU_AOUT gah;
  37. #if VCPI_ED
  38.   word32 edb_base;
  39. #endif
  40.   int fd;
  41.   char fn2[100], *fns;
  42.  
  43.   fd = _open(fn, O_RDONLY);
  44.  
  45.   if (fd < 0)
  46.   {
  47.     char *cp;
  48.     strcpy(fn2, argv0);
  49.     fns = 0;
  50.     for (cp=fn2; *cp; cp++)
  51.       if (strchr(":\\/", *cp))
  52.         fns = cp;
  53.     if (fns)
  54.     {
  55.       strcpy(fns+1, fn);
  56.       fd = _open(fn2, O_RDONLY);
  57.       if (fd >= 0)
  58.         fn = fn2;
  59.     }
  60.   }
  61.   
  62.   if (fd < 0)
  63.   {
  64.     char *path = getenv("PATH");
  65.     char *pathbeg=path, *pathsep;
  66.     while (1)
  67.     {
  68.       pathsep = pathbeg;
  69.       while (*pathsep && *pathsep != ';')
  70.         pathsep++;
  71.       strncpy(fn2, pathbeg, pathsep-pathbeg);
  72.       fn2[pathsep-pathbeg] = '/';
  73.       strcpy(fn2+(pathsep-pathbeg)+1, fn);
  74.       fd = _open(fn2, O_RDONLY);
  75.       if (fd >= 0)
  76.       {
  77.         fn = fn2;
  78.         break;
  79.       }
  80.       if (*pathsep == 0)
  81.         break;
  82.       pathbeg = pathsep+1;
  83.     }
  84.   }
  85.  
  86.   if (fd < 0)
  87.   {
  88.     fprintf(stderr, "Error: cannot open external debugger file %s\n", fn);
  89.     perror("The error was");
  90.     exit(1);
  91.   }
  92.   read(fd, &eh, sizeof(eh));
  93.   if (eh.f_magic != 0x14c)
  94.   {
  95.     fprintf(stderr, "Invalid external debugger %s - not COFF binary\n", fn);
  96.     exit(1);
  97.   }
  98.   read(fd, &gah, sizeof(gah));
  99.  
  100. #if VCPI_ED
  101.   if (use_DPMI) 
  102.     edb_base = 0;
  103.   else
  104.     edb_base = 0x90000000L;
  105.  
  106.   if (gah.entry != edb_base+0x0a8L)
  107.   {
  108.     fprintf(stderr, "Invalid external debugger %s - entry point not 0x%lx (is 0x%lx)\n", fn, edb_base+0xa8L, gah.entry);
  109.     if (gah.entry == 0x900000a8L)
  110.       fprintf(stderr, "Try using the DPMI binary - ed32-dpmi - instead\n");
  111.     if (gah.entry == 0xa8)
  112.       fprintf(stderr, "Try using the non-DPMI binary - edebug32 - instead\n");
  113.     exit(1);
  114.   }
  115. #endif
  116.  
  117.   memcpy(&ed_tss, &a_tss, sizeof(TSS));        /* clone a_tss */
  118.   tss_ptr = &ed_tss;
  119.   ed_tss.tss_eip = gah.entry;
  120.  
  121.   if (use_DPMI) {
  122.     AREAS dbgarea;
  123.     word32 newbytes;
  124.     DPMImemory dbgmem;
  125.     int dbgselect;
  126.     
  127.     dbgarea.first_addr = 0;
  128.     dbgarea.last_addr = gah.tsize + gah.dsize + 0xa7;
  129.     dbgarea.foffset = 0;
  130.     dbgarea.fileno = fd;
  131.  
  132.     newbytes = (dbgarea.last_addr + 0x100fffL) & ~0xfff;    /* 1Mb extra */
  133.     DPMIprotectedMode();
  134.     if (! DPMIalloc(&dbgmem, newbytes)) {
  135.       DPMIrealMode();
  136.       fprintf(stderr,"DPMI: Not enough memory for debugger (0x%08lx bytes).\n", newbytes);
  137.       exit(1);
  138.     }
  139.  
  140.     ourDSsel = _DS;            /* in protected mode, of course */
  141.     dbgselect = DPMIselector(2);    /* one for CS, one for SS/DS */
  142.  
  143.     DPMIassignSelector(dbgselect, 0xc0b3, dbgmem.address, dbgmem.bytes - 1 );
  144.     DPMIassignSelector(dbgselect+8, 0xc0bb, dbgmem.address, dbgmem.bytes - 1 );
  145.     DPMIrealMode();
  146.  
  147.     ed_tss.tss_ds = ed_tss.tss_es = ed_tss.tss_fs = 
  148.       ed_tss.tss_ss = dbgselect;
  149.     ed_tss.tss_cs = dbgselect + 8;
  150.     ed_tss.tss_esp = dbgmem.bytes - 12;
  151.     ed_tss.tss_eflags = 0x0202;
  152.  
  153.     loadAout(&dbgarea);
  154.     Pmemset(dbgselect, dbgarea.last_addr+1, 0, dbgmem.bytes-dbgarea.last_addr-1);
  155.  
  156.     close(fd);
  157.   } else {
  158.  
  159. #if VCPI_ED
  160.     areas[A_syms].first_addr = 0xa0000000L;
  161.     areas[A_syms].last_addr = 0xa00000a7L + gah.tsize + gah.dsize;
  162. #else
  163.     areas[A_syms].first_addr = 0xa0001000L;
  164.     areas[A_syms].last_addr = 0xa00010a7L + gah.tsize + gah.dsize;
  165. #endif
  166.     areas[A_syms].foffset = 0;
  167.     areas[A_syms].fileno = fd;
  168.  
  169.     areas[A_syms2].first_addr = areas[A_syms].last_addr+1;
  170.     areas[A_syms2].last_addr = 0xafffffffL;
  171.     areas[A_syms2].foffset = -1;
  172.  
  173. #if !VCPI_ED
  174.     ed_tss.tss_esp = 0x0ffffff4l;
  175.     ed_tss.tss_ds = g_edds * 8;
  176.     ed_tss.tss_es = g_edds * 8;
  177.     ed_tss.tss_ss = g_edds * 8;
  178.     ed_tss.tss_cs = g_edcs * 8;
  179.     ed_tss.tss_edi = 0;
  180.     ed_tss.tss_ebx = 0;
  181.     ed_tss.tss_ebp = 0;
  182. #else
  183.     ed_tss.tss_esp = 0x9ffffff4l;
  184. #endif
  185.     ourDSsel = g_rdata * 8;
  186.   }
  187.  
  188.   ext_debug_info.version = EXTERNAL_DEBUGGER_VERSION;
  189.  
  190.   ext_debug_info.a_tss_ofs = FP_OFF(&a_tss);
  191.   ext_debug_info.a_tss_seg = ourDSsel;
  192.  
  193.   ext_debug_info.filename_ofs = FP_OFF(running_fname);
  194.   ext_debug_info.filename_seg = ourDSsel;
  195.   ext_debug_info.filename_len = strlen(running_fname);
  196.  
  197.   ext_debug_info.areas_ofs = FP_OFF(&areas);
  198.   ext_debug_info.areas_seg = ourDSsel;
  199.  
  200.   ext_debug_info.app_base = ARENA;
  201.   ext_debug_info.ansi_mode = use_ansi;
  202.  
  203.   memset(ext_debug_info.dr, 32, 0);
  204.  
  205.   using_external_debugger = 1;
  206. }
  207.  
  208. void set_break_DPMI(void)
  209. {
  210.   int i,enabled,extract;
  211.   word16 sizetype;
  212.   word32 br_addr;
  213.  
  214.   enabled = (int)dr[7];
  215.   extract = (int)(dr[7] >> 16);
  216.   nset = 0;
  217.  
  218.   for(i=0;i<4;i++)
  219.     if( (enabled >> (i*2))&3 ) {
  220.       sizetype = (extract >> (i*4)) & 3;    /* extract the type */
  221.       if(sizetype == 3) sizetype = 2;       /* convert for DPMI brain damage */
  222.       sizetype = (sizetype << 8) + ((extract >> (i*4+2)) & 3) + 1; /* & size */
  223.       br_addr = dr[i] + DPMImem.address;
  224.       breakhandle[i] = DPMIsetBreak(sizetype, br_addr);
  225.       if(breakhandle[i] == -1)
  226.         fprintf(stderr,"Error allocating DPMI breakpoint at address 0x%08lx\n",dr[i]);
  227.       else
  228.         nset++;
  229.     } else
  230.       breakhandle[i] = -1;
  231.   return;
  232. }
  233.  
  234. void clear_break_DPMI(void)
  235. {
  236.   int i,bt;
  237.  
  238.   if(!nset) {
  239.     dr[6] = 0L;
  240.     return;
  241.   }
  242.  
  243.   bt = 0;
  244.   for(i=3;i>=0;i--) {
  245.     bt = bt << 1;                             /* Shift for next bit */
  246.     if(breakhandle[i] != -1)
  247.       bt |= DPMIcancelBreak(breakhandle[i]);  /* Set low bit if active */
  248.   }
  249.  
  250.   dr[6] = (word32)bt;
  251. }
  252.  
  253. int external_debugger_handler(void)
  254. {
  255.   static unsigned char old_enable;
  256.   if (tss_ptr != &ed_tss)
  257.     return 1;
  258.   switch ((word8)(tss_ptr->tss_eax))
  259.   {
  260.     case EXTERNAL_DEBUGGER_EXECUTE:
  261.       if(event_queue != NULL)            /* enable events */
  262.         event_queue->evq_enable = old_enable;
  263.       tss_ptr = &a_tss;
  264.       memcpy(dr, ext_debug_info.dr, 32);
  265.       if (use_DPMI)
  266.         set_break_DPMI();
  267.       go_til_stop();
  268.       if (use_DPMI)
  269.         clear_break_DPMI();
  270.       memcpy(ext_debug_info.dr, dr, 32);
  271.       if(event_queue != NULL) {            /* disable events */
  272.         old_enable = event_queue->evq_enable;
  273.         event_queue->evq_enable = 0;
  274.       }
  275.       if (a_tss.tss_irqn <= hard_master_hi && a_tss.tss_irqn >= hard_master_lo)
  276.         a_tss.tss_irqn -= hard_master_lo - 8;
  277.       if (a_tss.tss_irqn <= hard_slave_hi && a_tss.tss_irqn >= hard_slave_lo)
  278.         a_tss.tss_irqn -= hard_slave_lo - 0x70;
  279.       tss_ptr = &ed_tss;
  280.       return 0;
  281.  
  282.     case EXTERNAL_DEBUGGER_GETINFOPTR:
  283.       tss_ptr->tss_eax = FP_OFF(&ext_debug_info);
  284.       tss_ptr->tss_edx = ourDSsel;
  285.       return 0;
  286.  
  287.     default:
  288.       return 1;
  289.   }
  290. }
  291.  
  292.